/*
 * @Author: zhangyang
 * @Date: 2022-01-14 09:39:16
 * @LastEditTime: 2022-02-13 16:33:08
 * @Description: 抖音开放平台，主播直播数据爬取
 */
import { sleep, sleepRandomTime } from "~/utils/time";
import { youngExport } from "~/utils/youngExport";
export class ByteDanceGetter {
  /**
   * 数据集合
   */
  public dataMap = ref<DataItem[]>([]);
  /**
   * 分页描述
   */
  private pageSelector = '.leftInfo--2dSuF';
  /**
   * 下一页的按钮
   */
  private nextSelector = '.ant-pagination-next';
  /**
   * 当页所有主播
   */
  private masterSelector = '.semi-table-row';
  /**
   * 获取主播详情按钮
   */
  private mItemSelector = '.semi-table-cell-fixed-right-first';
  /**
   * 主播 uid 昵称
   */
  private nickSelector = '.copy-content--sF96b';
  /**
   * 主播每日的详细数据
   */
  private subSelector = '.semi-modal-body .semi-table-row';
  /**
   * 关闭弹出层
   */
  private closeSelecotr = '.semi-modal-close'
  
  /**
   * 读取当页主播的数据
   * @returns DataItem[]
   */
  readBrdData() {
    const arr = new Array<DataItem>();
    const rows = Array.from(document.querySelectorAll(this.masterSelector));
    rows.shift();
    for (const row of rows) {
      const [nickElement, uidElement] = Array.from((row as Element).querySelectorAll(this.nickSelector)) || [new Element(), new Element()];
      const nick = nickElement?.innerHTML;
      const uid = uidElement?.innerHTML;
      arr.push({ nick, uid });
    }
    return arr;
  };
  /**
   * 关闭弹出层
   */
  closeDialog() {
    const btn = document.querySelector(this.closeSelecotr) as HTMLButtonElement;
    btn.click();
  };
  /**
   * 读取主播详细数据
   */
  readBrdDetailData() {
    const dateObj: Record<string, string | number> = {};
    const rows = Array.from(document.querySelectorAll(this.subSelector));
    rows.shift();
    // console.log(rows);
    for (const row of rows) {
      const [dateElement, timeElement] = Array.from((row as Element).children) || [new Element(), new Element()];
      const date = dateElement.innerHTML;
      const [h, m, s] = timeElement.innerHTML.match(/\d+/img)?.map((i) => +i) || [0, 0, 0]
      const time = Math.floor((h * 3600 + m * 60 + s) / 60);
      dateObj[date] = time;
    }
    // console.log(dateObj);
    return dateObj;
  };
  /**
   * 打开弹出层
   */
  async openDetail(btn: HTMLButtonElement) {
    btn.click();
    await sleepRandomTime();
    const dateObj = this.readBrdDetailData();
    await sleepRandomTime();
    this.closeDialog();
  
    return dateObj;
  };
  /**
   * 遍历当前页
   */
  async everyCurrentPage() {
    // 读取当前页的主播数据
    const arr = this.readBrdData();
    // 遍历主播明细数据
    const btns = Array.from(document.querySelectorAll(this.mItemSelector));
    btns.shift();
    const len = btns.length;
    for (let index = 0; index < len; index++) {
      // 打开弹出层，读取每一个主播的明细数据
      const dateObj = await this.openDetail(btns[index].children[0] as HTMLButtonElement);
      arr[index] = { ...arr[index], ...dateObj };
    }
    this.dataMap.value.push(...arr);
  }
  /**
   * 判断是否为最后一页
   */
  isLast() {
    const txt = (document.querySelector(this.pageSelector) as HTMLSpanElement).innerText;
    const [last, total] = txt.match(/\d+/img)?.slice(1) || [1, 1] ;
    return last === total;
  }
  /**
   * 数据量是否超过一页
   */
  isMoreThanOne() {
    const txt = (document.querySelector(this.pageSelector) as HTMLSpanElement).innerText;
    const [_, total] = txt.match(/\d+/img)?.slice(1) || [1, 1] ;
    return total > 10;
  }
  /**
   * 下一页
   */
  nextPage() {
    const btn = document.querySelector(this.nextSelector);
    console.log(btn);
    (btn as HTMLButtonElement).click();
  }

  /**
   * 开始爬取
   */
  async start() {
    do {
      await this.everyCurrentPage();
      this.nextPage();
      await sleep(2 + Math.random() * 10);
    } while (!this.isLast());
    // 最后一页
    if (this.isMoreThanOne()) {
      await this.everyCurrentPage();
    }
    window.alert('爬取成功，即将下载(编程不易，点击右上角扩展图标可给作者充电)');
    this.exportHandler();
  }

  /**
   * 导出
   */
  async exportHandler() {
    type Head = {
      date: string;
      nick: string;
      uid: string;
      platform: string;
      time: string | number;
    };
    const tableHead: TableHeadItem<Head>[] = [
      { prop: 'date', label: '日期' },
      { prop: 'nick', label: '主播昵称' },
      { prop: 'uid', label: '平台账号' },
      { prop: 'platform', label: '平台' },
      { prop: 'time', label: '直播时长(分钟)' }
    ];
    const tableData: TableDataItem<Head>[] = [];
  
    for (const { nick, uid, ...dateObj } of this.dataMap.value) {
      for (const [date, time] of Object.entries(dateObj)) {
        const temp: TableDataItem<Head> = {
          nick,
          uid,
          date,
          time,
          platform: '抖音'
        };
        tableData.push(temp);
      }
    }
    await youngExport({
      filename: '抖音数据',
      tableHead,
      tableData
    });
    this.clear();
  }

  /**
   * 清空历史记录
   */
  clear() {
    this.dataMap.value.length = 0;
  }
}